package com.xiaowanzi.transporter.encoder;

import com.xiaowanzi.transporter.constants.Constants;
import com.xiaowanzi.transporter.constants.MessageTypeEnum;
import com.xiaowanzi.transporter.model.Message;
import com.xiaowanzi.transporter.util.SessionIdGenerator;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import java.nio.charset.Charset;
import org.springframework.util.StringUtils;

/**
 * 将request请求封装到一个字节数组中，其格式如下：
 * MAGIC_NUMBER + MAIN_VERSION + SUB_VERSION + MODIFY_VERSION + REQUEST_TYPE + ATTACHMENT_SIZE + ATTACHMENTS + BODY_LENGTH + BODY
 *     4        +       1      +       1     +        1       +       1      +        2        +   DYNAMIC   +      4      + DYNAMIC
 *
 * ATTACHMENTS:
 *   len + key + len + value
 *    4  + key +  4  + value
 */
public class MessageEncoder extends MessageToByteEncoder<Message> {

  @Override
  protected void encode(ChannelHandlerContext ctx, Message message, ByteBuf out) throws Exception {
    if (message.getMessageType() != MessageTypeEnum.EMPTY) {
      out.writeInt(Constants.MAGIC_NUMBER);
      out.writeByte(Constants.MAIN_VERSION);
      out.writeByte(Constants.SUB_VERSION);
      out.writeByte(Constants.MODIFY_VERSION);
      if (!StringUtils.hasText(message.getSessionId())) {
        String sessionId = SessionIdGenerator.generate();
        message.setSessionId(sessionId);
        out.writeCharSequence(sessionId, Charset.defaultCharset());
      }

      out.writeByte(message.getMessageType().getType());
      out.writeShort(message.getAttachments().size());
      message.getAttachments().forEach((key, value) -> {
        Charset charset = Charset.defaultCharset();
        out.writeInt(key.length());
        out.writeCharSequence(key, charset);
        out.writeInt(value.length());
        out.writeCharSequence(value, charset);
      });

      if (null == message.getBody()) {
        out.writeInt(0);
      } else {
        out.writeInt(message.getBody().length());
        out.writeCharSequence(message.getBody(), Charset.defaultCharset());
      }
    }
  }
}
